/***************************************************************************
 *   Copyright (C) 2008 by Camille Gallet   *
 *      *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "PrologEngine.hpp"

PrologEngine::PrologEngine(){
    try
    {
       pl = new PlInterface("./scripts/minimax.pl");
    }catch ( PlException &exception ){
       //TODO Handle the exception
       QMessageBox msgBox;
       msgBox.setText("Error: the IA script cannot be found" );
       msgBox.exec();
       exit(1);
    }
      

}

PrologEngine::~PrologEngine(){
    delete pl;
}

void PrologEngine::recupAskingMove(GameEngine::box* plateau, GameEngine::player p)
{
    // Récupère le meilleur coup et le renvoi au plateau
    Moving m = getBestMove(plateau, p);
    jouer(m, plateau, p);
}

void PrologEngine::coupValide(bool& ok,Moving &m, GameEngine::box* plateau, GameEngine::player p){ 
	//QMessageBox::information(NULL,"Renvoi au PrologEngine",QString("Coup :%1\nType :%2\nDe :%3\nA :%4").arg(ok).arg(m.getKind()).arg(m.getFrom()).arg(m.getTo()));
    QVector<QVector<QString> > res;
    QVector<QString> subres;
    QString subsubres;
    QStringList lstRes;
    bool ret=false;
    int mfrom,mto;
    mfrom = m.getFrom();
    mto = m.getTo();
    QVector<QString> arguments(3);
    QString joueur;
    //convert the board into a string prolog-readable
    QString tab("["),tab2("[");

    for (int i=0; i<8 ; i++){
       tab += QString("%1,").arg((int)plateau[i]);
    }
    tab += QString("%1]").arg((int)plateau[8]);
    if(m.getKind()==Moving::PUT_CHECKER)
        tab2 += QString("-1,");
    else
        tab2 += QString("%1,").arg(mfrom);
    tab2 += QString("%1,").arg(mto);
    tab2 += QString("%1]").arg((int)m.getKind());
   
    joueur = QString("%1").arg((int)p);
    arguments[0]=tab;
    arguments[1]=joueur;
    arguments[2]=tab2;
    //QMessageBox::information(NULL,"Affichage des Tab's",joueur + "\ntab : " + tab + "\ntab2 :"+ tab2);
    try{
        res = pl->plExecute("coup",arguments);//ask the prolog script

        subres= res.first();
        if (!subres.empty()){//Normally it always goes through
            subsubres = subres[0];
            if(subsubres=="yes")
                ret=true;
        }

    } catch ( PlException &exception )
    {
       //Nothing here
    }
    ok=ret;


}


bool PrologEngine::jouer(Moving &m, GameEngine::box* plateau, GameEngine::player p){ 
    QVector<QVector<QString> > res;
    QVector<QString> subres;
    QString subsubres;
    QStringList lstRes;
    bool ret=false;
    int mfrom,mto;
    mfrom = m.getFrom();
    mto = m.getTo();
    QVector<QString> arguments(4);
    QString joueur;
    //convert the board into a string prolog-readable
    QString tab("["),tab2("[");

    for (int i=0; i<8 ; i++){
       tab += QString("%1,").arg((int)plateau[i]);
    }
    tab += QString("%1]").arg((int)plateau[8]);
    if(m.getKind()==Moving::PUT_CHECKER)
        tab2 += QString("-1,");
    else
        tab2 += QString("%1,").arg(mfrom);
    tab2 += QString("%1,").arg(mto);
    tab2 += QString("%1]").arg((int)m.getKind());
    joueur = QString("%1").arg((int)p);
    //QMessageBox::information(NULL,"op",tab+"\n"+joueur+"\n"+tab2+"\n");
    arguments[0]=tab;
    arguments[1]=joueur;
    arguments[2]=tab2;

    try{
        res = pl->plExecute("jouer",arguments);//ask the prolog script

        subres= res.first();
        if (!subres.empty()){//Normally it always goes through
            subsubres = subres[3];
            subsubres.replace("[","");
            subsubres.replace("]","");
            lstRes = subsubres.split(",", QString::SkipEmptyParts);
            if(lstRes.size()==9){
                for(int i=0;i<9;i++){
                    plateau[i]=(GameEngine::box)lstRes[i].toInt();
                }
                ret=true;
            }

        }

    } catch ( PlException &exception )
    {
       //Nothing here
    }

return ret;

}

void PrologEngine::victoire(bool &vict,GameEngine::box* plateau, GameEngine::player p){ 
    QVector<QVector<QString> > res;
    QVector<QString> subres;
    QString subsubres;
    QStringList lstRes;
    bool ret=false;
    QVector<QString> arguments(2);
    QString joueur;
    //convert the board into a string prolog-readable
    QString tab("["),tab2("[");

    for (int i=0; i<8 ; i++){
       tab += QString("%1,").arg((int)plateau[i]);
    }
    tab += QString("%1]").arg((int)plateau[8]);

    joueur = QString("%1").arg((int)p);
    arguments[0]=tab;
    arguments[1]=joueur;

    try{
        res = pl->plExecute("victoire",arguments);//ask the prolog script

        subres= res.first();
        if (!subres.empty()){//Normally it always goes through
            subsubres = subres[0];
            if(subsubres=="yes")
                ret=true;
        }

    } catch ( PlException &exception )
    {
       //Nothing here
    }
    vict=ret;

}

Moving PrologEngine::getBestMove(GameEngine::box* plateau, GameEngine::player p){
    Moving ret;
    QVector<QVector<QString> > res;
    QVector<QString> subres;
    QString subsubres;
    QStringList lstRes;
    int from,to;

    QVector<QString> arguments(3);
    QString joueur;
    //convert the board into a string prolog-readable
    QString tab("[");

    for (int i=0; i<8 ; i++){
       tab += QString("%1,").arg((int)plateau[i]);
    }
    tab += QString("%1]").arg((int)plateau[8]);

    joueur = QString("%1").arg((int)p);
    arguments[0]=tab;
    arguments[1]=joueur;

    try{
        res = pl->plExecute("meilleur",arguments);//ask the prolog script

        subres= res.first();
        if (!subres.empty()){//Normally it always goes through
            subsubres = subres[2];
            //explode the string containing the result
            subsubres.replace("[","");
            subsubres.replace("]","");
            lstRes = subsubres.split(",", QString::SkipEmptyParts);

            if(lstRes.size()==3){////Normally it always goes through
               from = lstRes[0].toInt();
               to = lstRes[1].toInt();

               //fill ret
               ret.setKind((Moving::kind)lstRes[2].toInt());
               ret.setTo(to);
               if(ret.getKind() == Moving::MOVE_CHECKER || ret.getKind() == Moving::MOVE_SQUARE || ret.getKind() == Moving::MOVE_DOUBLE_SQUARE ){
                       ret.setFrom(from);
              }
            }else
               ret.setKind(Moving::MOVE_ERROR);
        }else
            ret.setKind(Moving::MOVE_ERROR);
    } catch ( PlException &exception )
    {
       ret.setKind(Moving::MOVE_ERROR);
    }
    return ret;
}

void PrologEngine::humanPlay(GameEngine::box* plateau, Moving &m, GameEngine::player p){
    jouer(m,plateau,p);
}
